/*
This file is part of MMM.

MMM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

MMM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with MMM.  If not, see <http://www.gnu.org/licenses/>.
*
* @package    MMM
* @author     Nikolaus Vahrenkamp
* @copyright  2013 High Performance Humanoid Technologies (H2T), Karlsruhe, Germany
*
*/

#ifndef __MMM_Converter_H_
#define __MMM_Converter_H_

#include "../../../MMMCore.h"
#include <Eigen/Core>
#include <string> 
#include <vector>
#include <map>

#include "../../../MMMImportExport.h"
#include "../../../Motion/Legacy/AbstractMotion.h"
#include "../../../Model/Model.h"

// using forward declarations here, so that the rapidXML header does not have to be parsed when this file is included
namespace rapidxml
{
    template<class Ch>
    class xml_node;
}

namespace MMM
{


/*!
	\brief An interface for all converter classes.
	A converter maps an input motion to an output motion.
	Two main applications are intended with converters
	\li Converters from (e.g. Vicon) Motion Data to an MMM model
	\li Converters from MMM to a robot model

	\see ConverterFactory
*/
class MMM_IMPORT_EXPORT Converter
{
public:
	EIGEN_MAKE_ALIGNED_OPERATOR_NEW

	Converter(const std::string &name);

	/*!
		Basic setup of a converter
		\param inputModel Specifies to which model the inputMotion is linked. In case MarkerMotions are used as input (e.g. Vicon->MMM) the input model can be empty.
		\param inputMotion The motion to convert.
		\param outputModel Setup the target model.
		\return true on success.
	*/
    virtual bool setup (ModelPtr inputModel, AbstractMotionPtr inputMotion, ModelPtr outputModel);
    /*!
        Setup the converter via a config XML filename. Custom parameters are parsed in the _setup method, which each converter has to implement.
    */
    virtual bool setupFile (const std::string &configFilename);
    virtual bool setupXML (const std::string &xmlString);

	//! Pass the joint order to this converter
	virtual void setupJointOrder(const std::vector<std::string> & jo);
	virtual std::vector<std::string> getJointOrder() const;

	/*!
		Convert complete motion
	*/
	virtual AbstractMotionPtr convertMotion() = 0;

	/*!
		Some converters may offer a stepwise conversion. 
		This method initializes the output for stepwise conversion
	*/
	virtual AbstractMotionPtr initializeStepwiseConversion() = 0;

	/*!
		Pass a partially converted motion in order to compute the next frame.
	*/
    virtual bool convertMotionStep(AbstractMotionPtr currentOutput, bool increment=true) = 0;

	/*!
        Returns the initial model fitting of the converter which is used to start the convertion process.
	*/
	Eigen::Matrix4f getInitialModelFitting();

    /*!
        Returns the initial joint value fitting of the converter which is used to start the convertion process.
    */
    std::map< std::string, float> getInitialJointFitting();

    // Model Size getter/setter
    float getSourceModelSize() {return mSourceModelSize;}
    float getTargetModelSize() {return mTargetModelSize;}

    void setSourceModelSize(float size) {mSourceModelSize = size;}
    void setTargetModelSize(float size) {mTargetModelSize = size;}

protected:
    //! first tag in xml configuration
    virtual bool _setup(rapidxml::xml_node<char>* rootTag) = 0;

	std::string name;
	ModelPtr inputModel;
	AbstractMotionPtr inputMotion;
	ModelPtr outputModel;

    float mSourceModelSize;
    float mTargetModelSize;

	Eigen::Matrix4f initialModelPose;
    std::map< std::string, float> initialJointValues;

	std::vector<std::string> jointOrder;
	
};

typedef boost::shared_ptr<Converter> ConverterPtr;

}

#endif 
